﻿using System;
using System.Collections.Generic;
using System.Text;
using RedCorona.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace HovisPresent.Net
{

	/// <summary>
	/// Messages sent from the master:
	/// 
	/// IsAlive - slave responds with YesAlive
	/// ChangeSlide filename nextfilename scriptHint - replacement for ChangeSlide. filenames relative to document path
	/// Stop - causes computer to explode (joke.. what you think it does?)
	/// CheckFileExists filename - checks if the file exists. No response if ok, Error if its missing (TODO)
	/// </summary>
	public enum MasterMessage { IsAlive, ChangeSlide, Stop, CheckFileExists };

	/// <summary>
	/// Messages sent from slave
	/// 
	/// Hello currentlyPlaying - upon connection respond with what's currently playing
	/// YesAlive - response to IsAlive
	/// OK -
	/// Complete - Playback of video has completed
	/// Error message - A general error in playback or opening
	/// </summary>
	public enum SlaveMessage { Hello, YesAlive, Complete, Error };

	/// <summary>
	/// Base of the client and server connections, provides functions for 
	/// validating messages
	/// </summary>
	public class Connection 
	{
		private static Regex separators = new Regex("(\\s|\")");

		/// <summary>
		/// Splits the message into items, separated by space, using
		/// quotes to encase items with spaces. MUST start with plain text
		/// command at start of line.
		/// There's probably a nice way of doing this with regexp, but
		/// this is a bit more understandable!
		/// </summary>
		/// <param name="message">The message.</param>
		/// <returns>array of items, or null if format error</returns>
		public string[] SplitMessage(string message) {
			List<string> results = new List<string>();

			string[] tokens = separators.Split(message);

			// make sure we have message and correct start
			if (tokens.Length == 0 || Char.IsWhiteSpace(tokens[0][0]) || tokens[0] == "\"")
				return null;
			
			bool inQuotes = false;
			StringBuilder quotedText=null;

			foreach (string token in tokens) {
				if (string.IsNullOrEmpty(token))
					continue;

				if ( Char.IsWhiteSpace(token[0]) ) {
					if (inQuotes)
						quotedText.Append(' ');
				} else if (token == "\"") {
					if (inQuotes) {
						results.Add(quotedText.ToString());
						inQuotes = false;
					} else {
						quotedText = new StringBuilder(message.Length);
						inQuotes = true;
					}
				} else {
					if (inQuotes)
						quotedText.Append(token);
					else
						results.Add(token);
				}
			}

			if (inQuotes)
				return null;

			return results.ToArray();
		}

		/// <summary>
		/// Creates the message. quotes if necessary
		/// </summary>
		/// <param name="command">The command.</param>
		/// <param name="p">The p.</param>
		/// <returns></returns>
		protected static string CreateMessage(string command, params object[] p) {
			StringBuilder rv = new StringBuilder(200);
			rv.Append(command);

			foreach(object o in p ) {
				string s = o.ToString();

				if (rv.Length!=0)
					rv.Append(' ');

				if (s.Length==0)
					rv.Append("\"\"");
				else if (s.Contains(" ")) {
					rv.Append('\"');
					string replaced = s.Replace("\"","\\\"");
					replaced = replaced.Replace("\r\n", " ");					
					rv.Append(replaced);
					rv.Append('\"');
				} else
					rv.Append(s);
			}
			return rv.ToString();
		}

	}

}
